package swc.smu.ui.custom;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;

import java.util.List;

import swc.smu.ui.R;

/**
 * Created by smu on 2016/5/10.
 */
public class SelectSeatView extends View {

    // Viewport extremes. See mCurrentViewport for a discussion of the viewport.
    //坐标轴的极限值
    private static final float AXIS_X_MIN = -1f;
    private static final float AXIS_X_MAX = 1f;
    private static final float AXIS_Y_MIN = -1f;
    private static final float AXIS_Y_MAX = 1f;

    public static final float OFFSET = 100;

    private RectF mCurrentViewport = new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);

    private RectF mContentRect = new RectF();
    private Paint paint = new Paint();

    private Paint leftLabelPaint = new Paint();
    private Paint leftLabelBackPaint = new Paint();

    private Paint topLabelPaint = new Paint();
    private Paint topLabelBackPaint = new Paint();

    private ScaleGestureDetector mScaleGestureDetector;
    private GestureDetectorCompat mGestureDetector;

    private float labelMargin;

    //left label attribute
    private float leftLabelWidth;
    private float leftLabelTextSize;
    private int leftLabelBackground;
    private int leftLabelTextColor;
    private float leftLabelHorizontalPadding;
    private float leftLabelVerticalPadding;

    //top label attribute
    private float topLabelHeight;
    private float topLabelTextSize;
    private int topLabelBackground;
    private int topLabelTextColor;
    private float topLabelHorizontalPadding;
    private float topLabelVerticalPadding;

    private float topLabelStart;

    private float lineHeight;
    private float columnWidth;

    private List<String> leftLabel;
    private List<String> topLabel;
    private String labelText;

    public SelectSeatView(Context context) {
        this(context, null, 0);
    }

    public SelectSeatView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SelectSeatView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs);
        initPaint();
    }

    public SelectSeatView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    /**
     *
     */
    public void initView(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SelectSeatView);
        leftLabelTextColor = array.getColor(R.styleable.SelectSeatView_left_label_text_color, Color.WHITE);
        leftLabelBackground = array.getColor(R.styleable.SelectSeatView_left_label_background_color, Color.GRAY);
        leftLabelTextSize = array.getDimension(R.styleable.SelectSeatView_left_label_text_size, sp2px(12));
        leftLabelWidth = array.getDimension(R.styleable.SelectSeatView_left_label_width, dp2px(20));
        leftLabelHorizontalPadding = array.getDimension(R.styleable.SelectSeatView_left_label_horizontal_padding, dp2px(0));
        leftLabelVerticalPadding = array.getDimension(R.styleable.SelectSeatView_left_label_vertical_padding, dp2px(8));

        topLabelTextColor = array.getColor(R.styleable.SelectSeatView_top_label_text_color, Color.GRAY);
        topLabelBackground = array.getColor(R.styleable.SelectSeatView_top_label_background_color, Color.WHITE);
        topLabelTextSize = array.getDimension(R.styleable.SelectSeatView_top_label_text_size, sp2px(12));
        topLabelHeight = array.getDimension(R.styleable.SelectSeatView_top_label_height, dp2px(20));
        topLabelHorizontalPadding = array.getDimension(R.styleable.SelectSeatView_top_label_horizontal_padding, dp2px(5));
        topLabelVerticalPadding = array.getDimension(R.styleable.SelectSeatView_top_label_vertical_padding, dp2px(0));

        labelMargin = dp2px(5);
    }

    public void initPaint() {
        paint.setAntiAlias(true);
        paint.setTextSize(sp2px(10));
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setColor(Color.BLACK);

        mScaleGestureDetector = new ScaleGestureDetector(getContext(), mScaleGestureDetectorListener);
        mGestureDetector = new GestureDetectorCompat(getContext(), mSimpleOnGestureListener);

        //left label text paint
        leftLabelPaint.setAntiAlias(true);
        leftLabelPaint.setTextSize(sp2px(14));
        leftLabelPaint.setTextAlign(Paint.Align.CENTER);
        leftLabelPaint.setColor(leftLabelTextColor);

        //left label background paint
        leftLabelBackPaint.setAntiAlias(true);
        leftLabelBackPaint.setStyle(Paint.Style.FILL);
        leftLabelBackPaint.setColor(leftLabelBackground);

        topLabelPaint.setAntiAlias(true);
        topLabelPaint.setTextSize(sp2px(12));
        topLabelPaint.setTextAlign(Paint.Align.CENTER);
        topLabelPaint.setColor(topLabelTextColor);

        topLabelBackPaint.setAntiAlias(true);
        topLabelBackPaint.setTextSize(sp2px(14));
        topLabelBackPaint.setColor(topLabelBackground);

        lineHeight = 3 * leftLabelTextSize;
        columnWidth = 2 * topLabelTextSize;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        Log.i("jss", "onSizeChanged");
        mContentRect.set(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.i("jss", "onLayout");
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.i("jss", "onMeasure");
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawTitleLabel(canvas);
        drawLeftLabel(canvas);
        drawTopLabel(canvas);
//        drawSeatData(canvas);
        //canvas.drawText("自定义界面",(mContentRect.right - mContentRect.left) / 2 + mContentRect.top, (mContentRect.bottom - mContentRect.top) / 2 + mContentRect.top ,paint);
    }

    /**
     * 绘制座位信息
     * @param canvas
     */
    private void drawSeatData(Canvas canvas) {
        canvas.save();
        RectF rectF = new RectF(labelMargin + 2 * topLabelTextSize, topLabelHeight + labelMargin + topLabelTextSize + leftLabelTextSize / 2, mContentRect.right, mContentRect.bottom);
        canvas.clipRect(rectF);
        drawSeat(canvas, rectF);
        canvas.restore();
    }

    private void drawSeat(Canvas canvas, RectF parentRectF) {
//        canvas.drawText("自定义界面",rectF.left, rectF.top + paint.getTextSize(), paint);
        float lHeight = OFFSET + 50;
        RectF rectF = new RectF(0 ,0 , 0, 0);
        for (int i = 0; i < 10; i++) { //行 Y
            lHeight += leftLabelTextSize * 3 / 2;
            float cWidth = OFFSET * 2;
            for(int j = 0; j < 10; j++) { //列 X
                cWidth += columnWidth;
                rectF.set(rectF.right , lHeight - lineHeight, cWidth, lHeight);
                canvas.save();
                canvas.clipRect(rectF);
                if(j % 2 == 0){
                    if(i % 2 == 0) {
                        canvas.drawColor(Color.YELLOW);
                    } else {
                        canvas.drawColor(Color.RED);
                    }
                } else {
                    if(i % 2 == 0) {
                        canvas.drawColor(Color.RED);
                    } else {
                        canvas.drawColor(Color.YELLOW);
                    }
                }
                canvas.drawText("["+j+","+i+"]", rectF.centerX(), rectF.centerY(), paint);
                canvas.restore();
            }
        }
    }

    /**
     * 绘制顶部菜单栏
     */
    private void drawTopLabel(Canvas canvas) {
        canvas.save();
        RectF topArea = new RectF(topLabelStart, labelMargin, mContentRect.right, labelMargin + topLabelHeight);
        canvas.clipRect(topArea);
        drawTopLabelText(canvas, topArea);
        canvas.restore();
    }

    /**
     * 顶部菜单栏文本绘制
     * @param canvas
     */
    private void drawTopLabelText(Canvas canvas, RectF rectF) {
        if(topLabel == null) {
            return;
        }
        int size = topLabel.size();
        for (int i = 0; i < size; i++) {
            String s = topLabel.get(i);
            float x = rectF.left + (i+ 1) * topLabelTextSize * 2;
            canvas.drawText(s, x, rectF.centerY(), topLabelPaint);
        }
    }

    /**
     * 绘制左侧边栏
     * @param can
     */
    private void drawLeftLabel(Canvas can) {
        can.save(); //保存当前Canvas
        RectF rectF = new RectF(labelMargin, topLabelHeight + labelMargin, leftLabelWidth + labelMargin, mContentRect.height() - labelMargin - leftLabelWidth);
        can.clipRect(rectF); //裁剪Canvas
        can.drawRoundRect(rectF, dp2px(10), dp2px(10), leftLabelBackPaint);
        drawLeftLabelText(can, rectF);
        can.restore();//重置Canvas恢复到初始化大小
    }

    /**
     * 绘制左侧label文本
     * @param canvas
     * @param rectF
     */
    private void drawLeftLabelText(Canvas canvas, RectF rectF) {
        if(leftLabel == null) {
            return;
        }
        int length = leftLabel.size();
        for(int i = 0; i < length; i++) {
            String str = leftLabel.get(i);
            float x = rectF.left + leftLabelWidth / 2 + leftLabelHorizontalPadding; //X轴坐标
            float y = rectF.top + (i + 1) * (leftLabelTextSize + leftLabelVerticalPadding); //Y轴坐标
            canvas.drawText(str, x, y, leftLabelPaint);
        }
    }

    private void drawTitleLabel(Canvas canvas) {
        canvas.save();
        if(labelText != null && !"".equals(labelText)) {
            float position = labelMargin + (topLabelTextSize * labelText.length() / 2);
            canvas.drawText(labelText, position, labelMargin + topLabelVerticalPadding + topLabelHeight / 2 , topLabelPaint);
            topLabelStart = labelMargin + (topLabelTextSize * labelText.length());
        } else {
            topLabelStart = labelMargin + leftLabelWidth;
        }
        canvas.restore();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean resule = mScaleGestureDetector.onTouchEvent(event);
        resule = mGestureDetector.onTouchEvent(event) || resule;
        return resule || super.onTouchEvent(event);
    }

    /**
     * sp 转PX
     * @param f
     * @return
     */
    public float sp2px(float f) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, f, Resources.getSystem().getDisplayMetrics());
    }

    /**
     * dp转px
     * @param d
     * @return
     */
    public float dp2px(float d) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, d, Resources.getSystem().getDisplayMetrics());
    }


    /**
     * 缩放手势监听
     */
    private final ScaleGestureDetector.OnScaleGestureListener mScaleGestureDetectorListener = new ScaleGestureDetector.SimpleOnScaleGestureListener() {

        private PointF viewportFocus = new PointF();
        private float lastSpanX;
        private float lastSpanY;

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            Log.i("jss", "onScaleBegin");
            lastSpanX = ScaleGestureDetectorCompat.getCurrentSpanX(detector);
            lastSpanY = ScaleGestureDetectorCompat.getCurrentSpanY(detector);
            return true;//super.onScaleBegin(detector);
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            Log.i("jss", "onScale");
            float spanX = ScaleGestureDetectorCompat.getCurrentSpanX(detector);
            float spanY = ScaleGestureDetectorCompat.getCurrentSpanY(detector);

            PointF previousPoint = new PointF();
            previousPoint.set(lastSpanX, lastSpanY);

            PointF currentPoint = new PointF();
            currentPoint.set(spanX, spanY);
            float dis = disPoint(previousPoint, currentPoint);

            ViewCompat.postInvalidateOnAnimation(SelectSeatView.this);
            lastSpanX = spanX;
            lastSpanY = spanY;
            return true;//super.onScale(detector);
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            super.onScaleEnd(detector);
            Log.i("jss", "onScaleEnd");
        }
    };

    private boolean hitTest(float x, float y, PointF dest) {
        if(!mContentRect.contains(x, y)) {
            return false;
        }
        dest.set(mCurrentViewport.left + mCurrentViewport.width() * (x - mContentRect.left) / mContentRect.width() ,
                mCurrentViewport.top + mCurrentViewport.height() * (y - mContentRect.bottom) / -mContentRect.height());
        return true;
    }

    /**
     * 手势监听
     */
    private final GestureDetector.SimpleOnGestureListener mSimpleOnGestureListener = new GestureDetector.SimpleOnGestureListener(){
        @Override
        public boolean onDown(MotionEvent e) {
            Log.i("jss", "mSimpleOnGestureListener onDown");
            return super.onDown(e);
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            Log.i("jss", "mSimpleOnGestureListener onDoubleTap");
            return super.onDoubleTap(e);
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            Log.i("jss", "mSimpleOnGestureListener onScroll");
            return super.onScroll(e1, e2, distanceX, distanceY);
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            Log.i("jss", "mSimpleOnGestureListener onFling");
            return super.onFling(e1, e2, velocityX, velocityY);
        }
    };

    /**
     * 两点之间的距离
     * @param lastPoint
     * @param currPoint
     */
    private float disPoint(PointF lastPoint, PointF currPoint) {

        double dis = Math.sqrt((currPoint.x - lastPoint.x)*(currPoint.x - lastPoint.x) + (currPoint.y-lastPoint.y) * (currPoint.y-lastPoint.y));

        return (float) dis;
    }

    public List<String> getLeftLabel() {
        return leftLabel;
    }

    public void setLeftLabel(List<String> leftLabel) {
        this.leftLabel = leftLabel;
    }

    public List<String> getTopLabel() {
        return topLabel;
    }

    public void setTopLabel(List<String> topLabel) {
        this.topLabel = topLabel;
    }

    public String getLabelText() {
        return labelText;
    }

    public void setLabelText(String labelText) {
        this.labelText = labelText;
    }
}
